package com.paraz.cst;

import static org.junit.Assert.*;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.Test;

/**
 * Test without any dependency injection tools.
 * @author mparaz
 *
 */
public class AsyncCstLooperTestCase {
	/**
	 * String to compare.
	 */
	private final String STR = "Hello World";

	@Test
	public void testAsyncLoop() {
		final TestCstProcessor<Integer> processor = new TestCstProcessor<Integer>(true);
		
		final AsyncCstLooper looper = new AsyncCstLooper();
		looper.setCstProcessor(processor);
		
		// Use an AtomicReference since we can make it final and set the value from from inner classes. 
		final AtomicReference<String> stringResult = new AtomicReference<String>();
		
		final AtomicInteger counter = new AtomicInteger();
		
		// Two-level layer of anonymous interfaces.
		// This is fine since we don't need to loop.
		//
		// We hook up a simple state machine to the simulated interface. 
		final CstSocket cstSocket = new CstSocket() {

			public CstInput getCstInput() {
				return new CstInput() {
					public String read() throws CstException {
						if (stringResult.get() == null) {
							// First time - the request
							return STR;
					 	} else {
					 		// Second time, the follow-up request
					 		return "P " + counter.get();
					 	}
					}
				};
			}

			public CstOutput getCstOutput() {
				return new CstOutput() {
					public void write(String output) throws CstException {
						// Verify the output
						if (stringResult.get() == null) {
							// First time, the signal to follow up
							assertTrue(output.startsWith("P"));
							stringResult.set(output);
						} else {
							// Second time, the result
							assertEquals(STR + AsyncCstLooper.LINE_TERMINATOR, output);
						}
					}
				};
			}
		};
		
		// Fire. One time only.
		looper.loop(true, cstSocket);
		
		// Verify that write() was called.
		// Avoid "Pass by Default."
		// write() called implies read() called.
		assertNotNull(stringResult.get());
	}
}
